package xmu.crms.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import xmu.crms.config.security.AuthServiceImpl;
import xmu.crms.config.security.MinProgramAuthorization;
import xmu.crms.dto.UserInfoDTO;
import xmu.crms.entity.School;
import xmu.crms.entity.User;
import xmu.crms.exception.InfoIllegalException;
import xmu.crms.exception.OpenIdDuplicateException;
import xmu.crms.exception.UserNotFoundException;
import xmu.crms.exception.WechatLoginException;
import xmu.crms.mapper.UserMapper;
import xmu.crms.service.SchoolService;
import xmu.crms.service.UserService;
import xmu.crms.util.JwtUtil;
import xmu.crms.vo.SchoolVO;
import xmu.crms.vo.SignInVO;
import xmu.crms.vo.UserInfoVO;

import java.io.IOException;
import java.math.BigInteger;
import java.util.Objects;

/**
 * @author status200
 * @date 2017/11/27
 */
@RestController
public class MeController {

    @Autowired
    private UserService userService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SchoolService schoolService;

    @Autowired
    private AuthServiceImpl authService;

    /**
     * 获取用户信息。
     * 用户的类型需要使用jwt进行判断。
     *
     * @return
     */
    @GetMapping("/me")
    public ResponseEntity<UserInfoVO> getMe(@RequestHeader("Authorization") String authString) throws UserNotFoundException {

        BigInteger userId = JwtUtil.getIdFromAuthString(authString);
        User user = userService.getUserByUserId(userId);
        UserInfoVO vo = new UserInfoVO();
        vo.setId(user.getId());
        Integer type = user.getType();
        if (type != null && type.equals(1)) {
            vo.setType("teacher");
        } else if(type != null && type.equals(0)){
            vo.setType("student");
        } else {
            vo.setType("");
        }

        vo.setName(user.getName());
        vo.setNumber(user.getNumber());
        vo.setPhone(user.getPhone());
        vo.setEmail(user.getEmail());
        vo.setAvatar(user.getAvatar());

        Integer male = user.getGender();
        if (male != null && male.equals(0)) {
            vo.setGender("male");
        } else if(male != null && male.equals(1)){
            vo.setGender("female");
        } else {
            vo.setGender("");
        }

        BigInteger schoolId = userMapper.getSchoolIdByUserId(userId);
        School school = schoolService.getSchoolBySchoolId(schoolId);

        if(school != null) {
            SchoolVO schoolVO = new SchoolVO();
            schoolVO.setId(school.getId());
            schoolVO.setName(school.getName());
            vo.setSchool(schoolVO);
        }
        vo.setTitle(vo.getTitle());
        vo.setAvatar(vo.getAvatar());

        return new ResponseEntity<>(vo, HttpStatus.OK);
    }

    @PutMapping("/me/unbind")
    public ResponseEntity unbindAccount(@RequestHeader("Authorization") String authString,@RequestBody UserInfoDTO dto) {
        BigInteger id = JwtUtil.getIdFromAuthString(authString);

        try {
            User user = userService.getUserByUserId(id);

            // 进行微信登录获得openid
            MinProgramAuthorization authorization = authService.doWechatLogin(dto.getJsCode());

            // 调用该api的用户的openid和发送过来的openid不一致
            if (!authorization.getOpenId().equals(user.getOpenid())) {
                throw new InfoIllegalException("User infomation not matched!");
            }

            // 设置用户的openid为null,即取消openid与账号之间的绑定
            user.setOpenid(null);
            userService.updateUserByUserId(user.getId(), user);

            return new ResponseEntity(HttpStatus.NO_CONTENT);

        } catch (WechatLoginException e) {
            e.printStackTrace();
            // 返回406
            return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
        } catch (IOException e) {
            e.printStackTrace();
            // 返回500
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (UserNotFoundException | InfoIllegalException e) {
            e.printStackTrace();
            // 返回403
            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
        }
    }

    /**
     * 绑定账号
     *
     * @param dto
     * @return
     */
    @PutMapping("/me")
    public ResponseEntity<SignInVO> bindAccount(@RequestBody UserInfoDTO dto) {

        // 进行绑定
        try {
            String jsCode = dto.getJsCode();
            MinProgramAuthorization authorization;

            authorization = authService.doWechatLogin(jsCode);

            User user = userMapper.getUserByTelephone(dto.getPhone());

            Integer type = "teacher".equals(dto.getType()) ? 1 : 0;

            // 是否存在该学号的用户
            if(user == null ) {
                throw new UserNotFoundException("Bind User Error!");
            }

            // 判断openid是否已经被绑定
            if(user.getOpenid() != null) {
                throw new OpenIdDuplicateException(String.format("Openid %s is already used", authorization.getOpenId()));
            }

            // 用户填写的绑定信息是否和用户一致
            if(!user.getSchool().getId().equals(dto.getSchool().getId()) ||
                    !user.getName().equals(dto.getName()) ||
                    !(user.getType().equals(type))) {
                throw new InfoIllegalException("User info error!");
            }

            user.setOpenid(authorization.getOpenId());
            userService.updateUserByUserId(user.getId(),user);
            SignInVO vo = authService.doMyLogin(authorization.getOpenId());

            return ResponseEntity.ok(vo);
        }
        // 该错误原因未知,但是必须抛出
        catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        // 微信登录错误，返回406
        catch (WechatLoginException e ) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
        }
        // 手机号不存在，返回401
        catch (UserNotFoundException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }
        catch (InfoIllegalException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
        }
        // openid 已经被使用
        catch (OpenIdDuplicateException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.CONFLICT);
        }
    }

    /**
     * 微信小程序/OAuth2登录
     */
    @GetMapping("/signin")
    public ResponseEntity<SignInVO> signIn(@RequestParam(value = "code", required = false) String code,
                                           @RequestParam("state") String state,
                                           @RequestParam(value = "success_url", required = false) String successUrl) {

        MinProgramAuthorization authorization;

        // 进行微信登录
        try {
            authorization = authService.doWechatLogin(code);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        // 微信登录错误，返回406
        catch (WechatLoginException e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
        }

        SignInVO vo;

        // 本程序的登录
        try {
            vo = authService.doMyLogin(authorization.getOpenId());

            return ResponseEntity.ok(vo);
        }

        // 不存在用户，直接抛出错误,返回401
        catch (UserNotFoundException e) {
            e.printStackTrace();

            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }
    }
}
